<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="content-type" content="no-cache, must-revalidate" />
    <meta http-equiv="expires" content="Wed, 26 Feb 1997 08:21:57 GMT" />
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
    <link rel="icon" href="[[ .staticBase ]]/favicon.ico" type="image/x-icon" crossorigin="anonymous" sizes="32x32"/>
    <title>[[ .title ]]</title>
    <script>
        window.APP_CONFIG = {
            title: "[[ .title ]]",
            baseurl: "[[ .baseurl ]]",
            shuiyin: "[[ .shuiyin ]]",
            staticBase: "[[ .staticBase ]]",
            componentBase: "[[ .componentBase ]]",
            version: "[[ .version ]]",
            demo: "no",
            initialConfigs: [[ .configs | toJson ]]
        };
        const version = window.APP_CONFIG.demo == 'yes' ? window.APP_CONFIG.version : '1';
        // 初始化动态加载CSS的方法
        window.loadStyle = (path) => {
            return new Promise((resolve, reject) => {
                const container = document.getElementById('dynamic-css');
                const newLink = document.createElement('link');
                newLink.rel = 'stylesheet';
                newLink.href = `${window.APP_CONFIG.staticBase}/${path}?v=${version}`;
                // 先添加新样式再移除旧样式
                newLink.onload = () => {
                    // 延迟200ms移除旧样式保证过渡
                    setTimeout(() => {
                        Array.from(container.children).forEach(oldLink => {
                            if (oldLink !== newLink) oldLink.remove();
                        });
                    }, 200);
                    resolve();
                };
                newLink.onerror = reject;
                container.appendChild(newLink);
            });
        };
    </script>
    <style>
        [v-cloak] {
            display: none;
        }
        #app .app-hidden {
            display: none !important;
        }
    </style>
    <link rel="stylesheet" href="[[ .staticBase ]]/element.css" />
    <script src="[[ .staticBase ]]/menus.js?v=[[ .version ]]"></script> <!-- 后台菜单 -->
    <script src="[[ .staticBase ]]/vue3.js"></script>
    <script src="[[ .staticBase ]]/vue-router.js"></script>
    <script src="[[ .staticBase ]]/router.js?v=[[ .version ]]"></script>
    <script src="[[ .staticBase ]]/element.js"></script>
    <script src="[[ .staticBase ]]/el-zh-cn.js"></script>
    <script src="[[ .staticBase ]]/axios.min.js"></script>
    <script src="[[ .staticBase ]]/qrcode.js"></script> <!-- 二维码 -->
    <script src="[[ .staticBase ]]/icons.js"></script> <!-- 图标 -->
    <script src="[[ .staticBase ]]/xlsx.full.min.js"></script>
    <script src="[[ .staticBase ]]/jszip.min.js"></script>
    <script src="[[ .staticBase ]]/x2js.js"></script>
    <script src="[[ .staticBase ]]/validator.js"></script>
    <script src="[[ .staticBase ]]/lodash.min.js"></script> <!-- 防抖节流 -->
    <script src="[[ .staticBase ]]/docx-preview.min.js"></script>
    <script src="[[ .staticBase ]]/crypto-js.js"></script>  <!-- 接口加解密 -->
    <script src="[[ .staticBase ]]/moment.min.js"></script> <!-- 时间处理 -->
    <script src="[[ .staticBase ]]/moment-zh-cn.js"></script>
    <script src="[[ .staticBase ]]/moment-timezone-with-data.min.js"></script>
    <script src="[[ .staticBase ]]/math.min.js"></script>
    <script src="[[ .staticBase ]]/kzh.js"></script>    <!-- 复用方法 -->
    <script src="[[ .staticBase ]]/api.js?v=[[ .version ]]"></script> <!-- api接口 -->
    <script src="[[ .staticBase ]]/print.min.js"></script>
    <script src="[[ .staticBase ]]/marked.min.js"></script> <!-- 富文本解析 -->
    <script src="[[ .staticBase ]]/highlight.min.js"></script>
    <script src="[[ .staticBase ]]/php.min.js"></script>
    <script src="[[ .staticBase ]]/Sortable.min.js"></script> <!-- 拖曳 -->
    <script src="[[ .staticBase ]]/vuedraggable.umd.min.js"></script>
    <script src="[[ .staticBase ]]/coordtransform.js"></script> <!-- 地图定位 -->
    <script src="https://map.qq.com/api/gljs?v=1.exp&key=OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77" charset="utf-8"></script>
    <script src="[[ .staticBase ]]/element-china-area-data.iife.js"></script> <!-- 省市县区 -->
</head>
<body>
      <!-- 动态样式容器 -->
    <div id="dynamic-css"></div>
    <div id="app" v-cloak style="display: none;flex-direction: column; height:calc(100vh - 1px);">
        <div class="body" style="flex-grow: 1; overflow: auto;"  v-if="isConfigsAvailable">
            <router-view></router-view>
        </div>
    
        <!-- 条件渲染底部 -->
        <div class="footer_bottom" v-if="isConfigsAvailable && configs.footer && !isAdminRoute" style="flex-shrink: 0;">
            <div class="footer_bottom_box" v-html="configs.footer"></div>
        </div>
    </div>
    <script setup>
        const { createApp, ref, onMounted, onUnmounted, onBeforeUnmount, computed, nextTick, watch,defineExpose, reactive, defineEmits, h, provide, readonly, inject } = Vue;
        const { ElMessage,  ElMessageBox, ElLoading, ElBreadcrumb, ElBreadcrumbItem, ElNotification } = ElementPlus;
        const QrcodeVue = window.QrcodeVue.default;
        const router = window.RouterConfig.router; // 从全局配置获取路由实例
        const App = {
            setup() {
                const speechState = reactive({enabled: true,rate: 1.0,pitch: 1.0})
                const initSpeech = () => {
                    SpeechManager.initForIOS();
                    document.removeEventListener('click', initSpeech);
                }
                if (navigator.userAgent.match(/iPhone|iPad/i)) {
                    document.addEventListener('click', initSpeech, { once: true });
                }
                // 增强版语音方法
                const smartSpeak = (message) => {
                    if (!speechState.enabled) return Promise.resolve()
                        return SpeechManager.speak(message, {
                        rate: speechState.rate,
                        pitch: speechState.pitch
                    })
                }
                provide('speech', { 
                    smartSpeak: (msg) => smartSpeak(msg).catch(console.error),
                    stop: SpeechManager.stop,
                    state: readonly(speechState)
                })
                const configs = ref(window.APP_CONFIG.initialConfigs || {});
                provide('globalConfigs', configs); // 全局配置
                const isConfigsAvailable = computed(() => configs.value && Object.keys(configs.value).length);
                const route = VueRouter.useRoute();
                
                onMounted(() => {
                    document.getElementById('app').style.display = 'flex';
                });
                
                // 判断是否是后台路由
                const isAdminRoute = computed(() => 
                    route.path.startsWith('/admin')
                );
                return {
                    configs,
                    isConfigsAvailable,
                    isAdminRoute,
                };
            }
        };
        const app = createApp(App).use(router).use(ElementPlus, { locale: ElementPlusLocaleZhCn });
        app.config.globalProperties.$validators = window.validators; // 全局注册validator.js验证方法
        for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
            app.component(key, component); //注册所有图标
        }
        app.component('draggable', window.vuedraggable); // draggable 注册
        app.component('qrcode-vue', QrcodeVue).mount('#app');
    </script>
</body>
</html>

<!--AddLocation可能属于导航或地图相关类型，AlarmClock属于时间管理，Apple属于食品或品牌，箭头类属于导航或方向指示，Avatar属于用户账户相关，Back可能是返回按钮，运动相关的如Baseball、Basketball属于运动类，Bell和BellFilled属于通知或提醒类，Bicycle属于交通工具，Bottom、BottomLeft、BottomRight属于方向或位置指示，Bowl、Box可能属于物品或容器，Briefcase属于商务或工作，Brush和BrushFilled属于绘图工具，Burger属于食品，Calendar属于时间管理，Camera属于媒体或摄影，Caret方向指示，Cellphone属于设备，Chat相关属于通讯或聊天，Check和Checked属于状态指示，Cherry、Chicken属于食品，ChromeFilled可能属于浏览器相关，CircleCheck等可能属于状态图标，Clock属于时间，Close属于关闭操作，Cloudy属于天气，Coffee、CoffeeCup属于食品饮料，Coin属于金融或货币，ColdDrink属于饮料，Collection属于集合或文件夹，Comment属于评论或沟通，Compass属于导航，Connection属于网络或连接，Coordinate属于位置，CopyDocument属于文档操作，Cpu属于硬件，CreditCard属于支付，Crop属于图片编辑，DArrowLeft等双箭头属于导航，DataAnalysis、DataBoard属于数据分析，Delete属于删除操作，Dessert属于食品，Discount属于商业促销，Dish属于餐具或食品，Document相关属于文档操作，Download属于下载，天气相关如Drizzling，Edit属于编辑，Eleme可能是一个品牌或特定应用，ElementPlus可能属于UI框架，Expand属于展开操作，Failed属于状态，Female、Male属于性别，Files属于文件管理，Film属于媒体，Filter属于筛选，Finished属于状态，FirstAidKit属于医疗，Flag属于标记，Fold属于折叠操作，Folder属于文件夹，Food属于食品，Football属于运动，ForkSpoon属于餐具，Fries属于食品，FullScreen属于视图模式，Goblet属于容器或食品，GoldMedal属于奖励，Goods属于商品，Grape属于食品，Grid属于布局，Guide属于帮助，Handbag属于配件，Headset属于设备，Help属于帮助，Hide属于隐藏操作，Histogram属于图表，HomeFilled属于主页，HotWater属于饮料，House属于建筑，IceCream属于食品，InfoFilled属于信息提示，Iphone属于设备，Key属于安全，KnifeFork属于餐具，Lightning属于天气或能源，Link属于超链接，List属于列表，Loading属于加载状态，Location属于位置，Lock属于安全，Lollipop属于食品，MagicStick可能属于工具或魔法主题，Magnet属于物理工具，Management属于管理，MapLocation属于地图，Medal属于奖励，Memo属于备忘录，Menu属于菜单，Message属于消息，Mic属于麦克风，Microphone属于设备，MilkTea属于饮料，Minus属于减少操作，Money属于金融，Monitor属于设备，Moon属于天气或时间，More属于更多操作，Mouse属于设备，Mug属于饮料，Mute属于声音控制，NoSmoking属于禁止标志，Notebook属于设备，Notification属于通知，Odometer属于车辆仪器，OfficeBuilding属于建筑，Open属于打开操作，Operation属于操作，Opportunity属于商业，Orange属于食品，Paperclip属于办公用品，PartlyCloudy属于天气，Pear属于食品，Phone属于设备，Picture属于图像，PieChart属于图表，Place属于位置，Platform属于平台，Plus属于添加操作，Pointer属于指针，Position属于位置，Postcard属于通讯，Pouring属于天气，Present属于礼物，PriceTag属于价格标签，Printer属于设备，Promotion属于促销，QuartzWatch属于设备，QuestionFilled属于帮助，Rank属于排名，Reading属于活动，Refresh属于刷新，Refrigerator属于家电，Remove属于移除操作，Right属于方向，ScaleToOriginal属于调整大小，School属于教育，Scissor属于工具，Search属于搜索，Select属于选择，Sell属于商业，SemiSelect属于部分选择，Service属于服务，SetUp属于设置，Setting属于设置，Share属于分享，Ship属于交通工具，Shop属于商业，Shopping相关属于购物，Smoking属于禁止标志，Soccer属于运动，SoldOut属于状态，Sort属于排序，Stamp属于邮票或标记，Star属于评分，Stopwatch属于时间，SuccessFilled属于状态，Sugar属于食品，Suitcase属于旅行，Sunny属于天气，Sunrise、Sunset属于时间，Switch属于开关，TakeawayBox属于食品，Ticket属于票务，Timer属于时间，ToiletPaper属于日用品，Tools属于工具，Top属于位置，TrendCharts属于图表，Trophy属于奖励，TurnOff属于关闭，Umbrella属于天气，Unlock属于安全，Upload属于上传，User属于用户，Van属于交通工具，VideoCamera属于设备，View属于查看，Wallet属于金融，Warning属于警告，Watch属于设备，Watermelon属于食品，WindPower属于能源，ZoomIn、ZoomOut属于缩放。-->